﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Songhay.Xml
{
    using Extensions;
    using Models;

    /// <summary>
    /// Static helpers for OPML.
    /// </summary>
    public static partial class OpmlUtility
    {

        /// <summary>
        /// Conventional namespace for OPML documents.
        /// </summary>
        public static XNamespace rx { get { return "http://songhaysystem.com/schemas/opml.xsd"; } }

        /// <summary>
        /// Gets the body.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="rx">The rx.</param>
        public static OpmlBody GetBody(XContainer root, XNamespace rx)
        {
            if(root == null) return null;

            var data = new OpmlBody
            {
                Outlines = GetOutlines(root, rx)
            };

            return data;
        }

        /// <summary>
        /// Gets the head.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="rx">The rx.</param>
        public static OpmlHead GetHead(XContainer root, XNamespace rx)
        {
            if(root == null) return null;

            var data = new OpmlHead
            {
                OwnerEmail = root.Elements(rx + "ownerEmail").ToElementValueOrNull(),
                OwnerName = root.Elements(rx + "ownerName").ToElementValueOrNull(),
                Title = root.Elements(rx + "title").ToElementValueOrNull()
            };

            var s = string.Empty;

            s = root.Elements(rx + "dateCreated").ToElementValueOrNull();
            if(!string.IsNullOrEmpty(s)) data.DateCreated = FrameworkTypeUtility.ParseRfc822DateTime(s);

            s = root.Elements(rx + "dateModified").ToElementValueOrNull();
            if(!string.IsNullOrEmpty(s)) data.DateModified = FrameworkTypeUtility.ParseRfc822DateTime(s);

            return data;
        }

        /// <summary>
        /// Gets the outline.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="rx">The rx.</param>
        public static OpmlOutline GetOutline(XElement root, XNamespace rx)
        {
            if(root == null) return null;

            var data = new OpmlOutline
            {
                Category = root.ToAttributeValueOrNull("category"),
                Id = root.ToAttributeValueOrNull("id"),
                Outlines = GetOutlines(root, rx),
                Text = root.ToAttributeValueOrNull("text"),
                Title = root.ToAttributeValueOrNull("title"),
                OutlineType = root.ToAttributeValueOrNull("type"),
                Url = root.ToAttributeValueOrNull("url"),
                XmlUrl = root.ToAttributeValueOrNull("xmlUrl")
            };

#if !SILVERLIGHT
            if(data.Url != null)
                data.Url = Environment.ExpandEnvironmentVariables(data.Url);
            if(data.XmlUrl != null)
                data.XmlUrl = Environment.ExpandEnvironmentVariables(data.XmlUrl);
#endif

            return data;
        }

        /// <summary>
        /// Gets the document.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="rx">The conventional namespace.</param>
        public static OpmlDocument GetDocument(XContainer root, XNamespace rx)
        {
            if(root == null) return null;

            var data = new OpmlDocument
            {
                OpmlBody = GetBody(root.Element(rx + "body"), rx),
                OpmlHead = GetHead(root.Element(rx + "head"), rx)
            };

            return data;
        }

        /// <summary>
        /// Gets the outlines.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="rx">The rx.</param>
        public static OpmlOutline[] GetOutlines(XContainer root, XNamespace rx)
        {
            if(root == null) return null;

            var data = new List<OpmlOutline>();
            root
                .Elements(rx + "outline")
                .ForEachInEnumerable(o =>
                {
                    var outline = GetOutline(o, rx);
                    if(outline != null)
                    {
                        outline.Outlines = GetOutlines(o, rx);
                        data.Add(outline);
                    }
                });

            return data.ToArray();
        }
    }
}
